// 2-3 c++多态-纯虚函数

/**
 * 面向对象的编程语言有封装、继承 、抽象、多态等4个主要的特征
 * 
 * C++ 多态
 * 多态按字面的意思就是多种形态。当类之间存在层次结构，并且类之间是通过继承关联时，就会用到多态。
 * 
 * C++ 多态意味着调用成员函数时，会根据调用函数的对象的类型来执行不同的函数。
 * 
 * ----------------------------------
 * 纯虚函数
 * 您可能想要在基类中定义虚函数，以便在派生类中重新定义该函数更好地适用于对象，但是您在基类中又不能对虚函数给出有意义的实现，这个时候就会用到纯虚函数。
 * 
 * 我们可以把基类中的虚函数 printArea() 改写如下（示例1）：
   
      virtual void printArea() = 0;

 * = 0 告诉编译器，函数没有主体，上面的虚函数是纯虚函数。
 * 包含存虚函数的类是抽象类。抽象类不能定义实例。
*/

#include <iostream>
#define __mark 1

/**
 * #1 示例一
*/
#if __mark == 1
class Shape
{
protected:
  int width;
  int height;

public:
  Shape(int a, int b) : width(a), height(b)
  {
  }
  // virtual void printArea()
  // {
  //   std::cout << "parent class area : " << 0 << std::endl;
  // }
  // pure virtual function 纯虚函数
  virtual void printArea() = 0;
  // virtual void printArea(); //  undefined reference to `vtable for Shape'
};

class Rectangle : public Shape
{
public:
  // 调用Shape的构造函数
  Rectangle(int a, int b) : Shape(a, b) {}

public:
  void printArea()
  {
    std::cout << "Rectangle class area : " << (width * height) << std::endl;
  }
};

class Triangle : public Shape
{
public:
  Triangle(int a, int b) : Shape(a, b)
  {
  }
  void printArea()
  {
    std::cout << "Triangle class area : " << (double)(width * height) / 2 << std::endl;
  }
};

int main(void)
{
  Shape *sp;
  // Shape s1(1,2);// error: cannot declare variable 's1' to be of abstract type 'Shape'

  Rectangle r1(3, 4);
  Triangle t1(4, 5);
  sp = &r1;
  sp->printArea();

  sp = &t1;
  sp->printArea();
  printf("-----------------end--------------\n");
  return 0;
}
#endif